﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;

namespace Perovich.GameObjects.Tools.Util
{
    public class AutoEvent
    {
        private CodeMemberEvent ev;

        public CodeMemberEvent Ev
        {
            get
            {
                if (!string.IsNullOrEmpty(Summary)) ev.Comments.Add(new CodeCommentStatement("<summary>" + Summary + "</summary", true));
                return ev;
            }
        }
        private CodeAttachEventStatement atch;

        public CodeAttachEventStatement Atch
        {
            get { return atch; }
        }
        private CodeMemberMethod meth;
        private CodeExpression target;

        public CodeMemberMethod Meth
        {
            get { return meth; }
        }

        public bool IsAutoEvent
        {
            get
            {
                return (target == null);
            }
        }

        private string summary;

        public string Summary
        {
            get
            {
                return summary;
            }
            set
            {
                summary = value;
            }
        }


        public AutoEvent(string name, string type, CodeEventReferenceExpression target = null, MemberAttributes attri = MemberAttributes.Public | MemberAttributes.Final)
        {
            this.target = target;
            if (target == null)
            {
                this.ev = new CodeMemberEvent();
                ev.Name = name;
                ev.Type = new CodeTypeReference("EventHandler", new CodeTypeReference(type));
                ev.Attributes = attri;
            }
            else
            {
                this.ev = new CodeMemberEvent();
                ev.Name = name;
                ev.Type = new CodeTypeReference("EventHandler", new CodeTypeReference(type));
                ev.Attributes = attri;

                this.atch = new CodeAttachEventStatement(target, new CodeDelegateCreateExpression(ev.Type, new CodeThisReferenceExpression(), string.Concat("On", name)));

                this.meth = new CodeMemberMethod();
                this.meth.Name = string.Concat("On", name);
                this.meth.Attributes = MemberAttributes.Family;
                this.meth.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object),"sender"));
                this.meth.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(type),"e"));
                this.meth.Comments.Add(new CodeCommentStatement("<summary>Fires the " + name + " event.</summary>", true));
                var even = new CodeEventReferenceExpression(new CodeThisReferenceExpression(), name);
                var arg = new CodeArgumentReferenceExpression("sender");
                var arg2 = new CodeArgumentReferenceExpression("e");
                this.meth.Statements.Add(
                    new CodeConditionStatement(
                        new CodeBinaryOperatorExpression(
                            even, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)
                        ),
                        new CodeStatement[] { new CodeExpressionStatement(new CodeDelegateInvokeExpression(even,arg,arg2)) }
                    ));
            }
        }

    }
}
